/**
 * $Id: PersonnelService.java 6 2011-09-14 00:18:07Z adriftrock@gmail.com $
 */

package com.swehr.server.services.impl;

import com.swehr.server.daos.IOrganizationDao;
import com.swehr.server.daos.IPersonnelDao;
import com.swehr.server.daos.IPositionDao;
import com.swehr.server.models.Organization;
import com.swehr.server.models.Personnel;
import com.swehr.server.models.Position;
import com.swehr.server.models.ResultInfo;
import com.swehr.server.services.IPersonnelService;
import com.swehr.utils.StringUtil;
import com.google.inject.Inject;
import org.apache.log4j.Logger;

import java.util.ArrayList;
import java.util.List;

/**
 * @author Rock Huang
 * @version 0.1
 */
public class PersonnelService implements IPersonnelService {

    private static Logger logger = Logger.getLogger(PersonnelService.class);

    @Inject private IOrganizationDao dao;

    @Inject private IPersonnelDao psnDao;

    @Inject private IPositionDao posDao;

    public List<Organization> list() {
        return dao.find();
    }

    public List<Organization> listSubOrg(String parentId) {
        return dao.findSubOrg(parentId);
    }

    public List<Personnel> listPsn() {
        return psnDao.find();
    }

    public List<Personnel> listPsnByOrg(String oid) {
        return psnDao.findByOrg(oid);
    }

    public List<Personnel> listPsnByPos(String pid) {
        return psnDao.findByPos(pid);
    }

    public List<Position> listPosByOrg(String orgId) {
        return posDao.findByOrg(orgId);
    }

    public Organization getOrgRoot(String id) {
        return dao.findOrgRoot(id);
    }

    public Organization signin(Organization org) {
        try {
           org = dao.findByEmailPsw(org.getEmail(), org.getPassword());
        } catch (Exception e) {
            String err = "Sign in verification failed. " + e;
            logger.error(err);
            org.setId(0);
            org.setComment(err);
        }
        return org;
    }

    /**
     * currently, return org object, the client need to check ID property,
     * if the id equals zero that means the saving operation is failed.
     * TODO: consider about that should an Organization need to convey more info.
     *
     * @param org Organization
     */
    public void add(Organization org) {
        logger.debug("add(): accept a raw Organization instance: \n" + org);
        try {
            dao.save(org);
            if (org.getId() > 0 && !StringUtil.isEmptyOrNull(org.getWebsite())) {
                dao.linkOrgResource(String.valueOf(org.getId()), org.getWebsite());
            }
        } catch (Exception e) {
            logger.error("add(): FAILED SAVING", e);
        }
    }

    public void update(Organization org) {
        logger.debug("update(): a Org instance want to be update: \n" + org);
        try {
            dao.update(org);
        } catch (Exception e) {
            logger.error("update(): FAILED UPDATING", e);
        }
    }

    public ResultInfo delete(int id) {
        ResultInfo info = new ResultInfo();
        try {
            if (dao.delete(id)) {
                info.setMessage(String.valueOf(id));
                info.setSuccess(true);
            }
        } catch(Exception e) {
            logger.error("delete(): FAILED SAVING.", e);
            info.setMessage("FAILED DELETING " + e.getMessage());
        }
        return info;
    }

    public ResultInfo savePsns(List<Personnel> psns) {
        List<Personnel> created = null;
        List<Personnel> updated = null;
        ResultInfo info = new ResultInfo(true, "");
        String[] removed = null;
        for (Personnel e : psns) {
            if (e.getId() == 0) {
                if (created == null) {
                    created = new ArrayList<Personnel>();
                }
                created.add(e);
            }
            if (e.getId() > 0) {
                if (updated == null) {
                    updated = new ArrayList<Personnel>();
                }
                updated.add(e);
            }
            if (e.getId() == -1) {
                String temp = e.getComment();
                if (temp.startsWith("[")) temp = temp.substring(1);
                if (temp.endsWith("]")) temp = temp.substring(0, temp.length() - 1);
                removed = temp.split(",");
            }
        }

        try {
            boolean isCreated, isUpdated, isRemoved;
            if (created != null) {
                isCreated = psnDao.batchSave(created);
                if (!isCreated) {
                    info.setSuccess(false);
                    info.setMessage("Failed Creating Personnel");
                }
            }
            if (updated != null) {
                isUpdated = psnDao.batchUpdate(updated);
                if (!isUpdated) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                        ? "Failed Updating Personnel" : ", Updating Personnel";
                    info.setMessage(msg);
                }
            }
            if (removed != null) {
                isRemoved = psnDao.batchRemove(removed);
                if (!isRemoved) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                          ? "Failed Rmoving Personnel" : ", Removing Personnel";
                    info.setMessage(msg);
                }
            }
        } catch (Exception e) {
            logger.error(e);
            e.printStackTrace();
            info.setSuccess(false);
            info.setMessage(info.getMessage() + " \n " + e.getMessage());
        }

        return info;
    }

    public ResultInfo batchSave(List<Organization> orgs) {
        List<Organization> created = null;
        List<Organization> updated = null;
        ResultInfo info = new ResultInfo(true, "");
        String[] removed = null;
        for (Organization o : orgs) {
            if (o.getId() == 0) {  // id==0 indicates this is a new Org
                if (created == null) {
                    created = new ArrayList<Organization>();
                }
                created.add(o);
            }
            if (o.getId() > 0) {  // id>0 indicates this is a saved org and need to update
                if (updated == null) {
                    updated = new ArrayList<Organization>();
                }
                updated.add(o);
            }
            if (o.getId() == -1) { // id==-1 indicates the Org convey indexes to delete
                String temp = o.getComment();
                if (temp.startsWith("[")) temp = temp.substring(1);
                if (temp.endsWith("]")) temp = temp.substring(0, temp.length() - 1);
                removed = temp.split(",");
            }
        }

        try {
            boolean isCreated, isUpdated, isRemoved;
            if (created != null) {
                isCreated = dao.batchSave(created);
                if (!isCreated) {
                    info.setSuccess(false);
                    info.setMessage("Failed Creating");
                }
            }
            if (updated != null) {
                isUpdated = dao.batchUpdate(updated);
                if (!isUpdated) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                                         ? "Failed Updating" : ", Updating";
                    info.setMessage(msg);
                }
            }
            if (removed != null) {
                isRemoved = dao.batchRemove(removed);
                if (!isRemoved) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                                          ? "Failed Rmoving" : ", Removing";
                    info.setMessage(msg);
                }
            }
        } catch (Exception e) {
            logger.error(e);
            e.printStackTrace();
            info.setSuccess(false);
            info.setMessage(info.getMessage() + " \n " + e.getMessage());
        }

        return info;
    }

    public ResultInfo savePos(List<Position> pos) {
        List<Position> created = null;
        List<Position> updated = null;
        ResultInfo info = new ResultInfo(true, "");
        String[] removed = null;
        for (Position p : pos) {
            if (p.getId() == 0) {
                if (created == null) {
                    created = new ArrayList<Position>();
                }
                created.add(p);
            }
            if (p.getId() > 0) {
                if (updated == null) {
                    updated = new ArrayList<Position>();
                }
                updated.add(p);
            }
            if (p.getId() == -1) {
                String temp = p.getComment();
                if (temp.startsWith("[")) temp = temp.substring(1);
                if (temp.endsWith("]")) temp = temp.substring(0, temp.length() - 1);
                removed = temp.split(",");
            }
        }

        try {
            boolean isCreated, isUpdated, isRemoved;
            if (created != null) {
                isCreated = posDao.batchSave(created);
                if (!isCreated) {
                    info.setSuccess(false);
                    info.setMessage("Failed Creating Position");
                }
            }
            if (updated != null) {
                isUpdated = posDao.batchUpdate(updated);
                if (!isUpdated) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                        ? "Failed Updating Position" : ", Updating Position";
                    info.setMessage(msg);
                }
            }
            if (removed != null) {
                isRemoved = posDao.batchRemove(removed);
                if (!isRemoved) {
                    info.setSuccess(false);
                    String msg = StringUtil.isEmptyOrNull(info.getMessage())
                          ? "Failed Rmoving Position" : ", Removing Position";
                    info.setMessage(msg);
                }
            }
        } catch (Exception e) {
            logger.error(e);
            e.printStackTrace();
            info.setSuccess(false);
            info.setMessage(info.getMessage() + " \n " + e.getMessage());
        }

        return info;

    }
}
